home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_09_12 / 9n12075a < prev    next >
Text File  |  1991-07-25  |  17KB  |  443 lines

  1. /** LISTING 3 ** UARTLOW.C ***************************
  2.  
  3.    Low level device driver routines for UART
  4. *****************************************************/
  5. #define UARTMAIN 1       
  6.  
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <stddef.h>
  11. #include <dos.h>
  12.  
  13. #include "uart.h"
  14. #include "uartmacs.c"
  15.  
  16. /* 
  17.  *  Compile Options  :  /AL /Ox /Zp /c
  18.  *           (Large library, optimization
  19.  *            for maxium speed, pack structures).
  20.  *           Note: /Ox does the following optimizations
  21.  *              Relaxed alias checking
  22.  *              Loop optimization
  23.  *              Intrinsic substitution
  24.  *              Optimization for speed
  25.  *              Removing stack probing
  26. */
  27. #pragma check_stack(off)
  28.  
  29. void interrupt far Asynch_driver(void)
  30. {              
  31.    register int value_from_port;   
  32.    register int cur_char;
  33.    static unsigned char near cur_port;
  34.    static struct t_port_info *p_cur_port_info; 
  35.    static int near interrupts_processed;
  36.    static int near i;  
  37.    static char *p_temp;
  38.    static char tx_char;
  39.  
  40.    /* Note - interrupts are automatically disabled by
  41.              CPU before entering interrupt routine. */
  42.    
  43.    do 
  44.    {   /* Loop until we make one complete pass 
  45.           without processing any interrupts */
  46.  
  47.        /* Set flag indicating that we haven't 
  48.           processed any interrupts on this pass
  49.           through the loop yet. */
  50.        interrupts_processed = 0;  
  51.  
  52.        /* Address the port entry of the first port in 
  53.           the system. */
  54.        p_cur_port_info = gp_port_info;
  55.        for (cur_port=1;cur_port<=g_num_ports;
  56.             cur_port++)
  57.        {   /* Loop through all the ports */
  58.  
  59.            /* read port's interrupt identification register */
  60.            value_from_port = inp(p_cur_port_info->
  61.                base_address+INTERRUPT_IDENT_REGISTER);
  62.  
  63.            if ( value_from_port & 0x01 )  
  64.            {   /* No interrupt pending */
  65.            
  66.                /* If less than MAX_RCVFIFO characters
  67.                   have been read without receiving a
  68.                   receive data interrupt, check line 
  69.                   status register to see if there is 
  70.                   still data in the FIFO.  This code
  71.                   will function correctly even if there
  72.                   isn't a FIFO. */
  73.                if (p_cur_port_info->non_int_chars < 
  74.                    MAX_RCVFIFO)
  75.                {
  76.                    /* read port's line status register */
  77.                    value_from_port = 
  78.                        inp(p_cur_port_info->
  79.                            base_address +
  80.                            LINE_STATUS_REGISTER);
  81.  
  82.                    /* Delay for port to catch up */
  83.                    IO_DELAY(1);         
  84.  
  85.                    if ( value_from_port & 0x01 )
  86.                    {   /* Data is ready */
  87.  
  88.                        /* Increment number of chars 
  89.                           processed from fifo without 
  90.                           interrupt */
  91.                        p_cur_port_info->
  92.                            non_int_chars++;
  93.  
  94.                        /* We have found at least one 
  95.                           interrupt pending so we will 
  96.                           have to make at least one 
  97.                           more pass. */
  98.                        interrupts_processed = 1;       
  99.  
  100.                        /* Skip normal interrupt 
  101.                           identification logic, and go
  102.                           right to reading the data. */
  103.                        goto force_read_data;
  104.                    }   /* End data is ready */
  105.  
  106.                }   /* End p_cur_port_info->
  107.                       non_int_chars < MAX_RCVFIFO) */
  108.            }   /* end no interrupt pending */
  109.            else
  110.            {   /* There is an interrupt pending
  111.                   from this port */
  112.                /* We have found at least one interrupt 
  113.                   pending so we will have to make at 
  114.                   least one more pass. */
  115.                interrupts_processed = 1;
  116.  
  117.                /* Mask out unwanted bits from interrupt
  118.                   identification.  */
  119.                value_from_port &= IIR_MASK;        
  120.  
  121.                switch (value_from_port)
  122.                {   /* Conditional execution depending
  123.                       on type of interrupt */
  124.  
  125.                    /* Interrupt for Receiver Line
  126.                       Status */
  127.                    case 0x06 :
  128.  
  129.                        /* Clear receive register */
  130.                        cur_char =
  131.                            inp(p_cur_port_info->
  132.                                base_address +
  133.                                RECEIVE_REGISTER);
  134.  
  135.                        /* Clear high word of character
  136.                           before breaking down error */
  137.                        cur_char &= 0x00ff;
  138.  
  139.                        /* read port's line status 
  140.                           register */
  141.                        value_from_port = 
  142.                            inp(p_cur_port_info->
  143.                                base_address + 
  144.                                LINE_STATUS_REGISTER);
  145.  
  146.                        if (value_from_port & 0x10)
  147.                        {   /* Received 'break' */ 
  148.                            cur_char |= BREAK_SIGNAL;
  149.                        }   
  150.  
  151.                        if (value_from_port & 0x08)
  152.                        {   /*  framing error */
  153.                            cur_char |= FRAMING_ERROR;
  154.                        }   
  155.            
  156.                        if (value_from_port & 0x04)
  157.                        {   /* parity error */
  158.                            cur_char |= PARITY_ERROR;
  159.                        }   
  160.            
  161.                        if (value_from_port & 0x02)
  162.                        {   /* overrun error */
  163.                            cur_char |= OVERRUN_ERROR;
  164.                        }   
  165.  
  166.                        goto add_char_to_rx_buf;
  167.  
  168.  
  169.                    /* Interrupt for data received */
  170.                    case 0x04 :
  171.                    
  172.                        /* Check line status register to
  173.                           see if data is ready */
  174.                        value_from_port = 
  175.                            inp(p_cur_port_info->
  176.                                base_address +
  177.                                LINE_STATUS_REGISTER);
  178.                        if ( !(value_from_port & 0x01) )
  179.                            break;
  180.  
  181.                        /* Set number of characters 
  182.                           received without data receive
  183.                           interrupt to 0. */
  184.                        p_cur_port_info->
  185.                            non_int_chars = 0;     
  186.  
  187.                        force_read_data:
  188.  
  189.                        /* read received data 
  190.                           register */
  191.                        cur_char =
  192.                            inp(p_cur_port_info->
  193.                                base_address+
  194.                                RECEIVE_REGISTER);
  195.  
  196.                        /* Clear high word of character
  197.                           before breaking down error */
  198.                        cur_char &= 0x00ff;
  199.  
  200.                        add_char_to_rx_buf:
  201.  
  202.                        /* Calculate pointer to next
  203.                           position in circular 
  204.                           receive buffer */
  205.                        p_temp = p_cur_port_info->
  206.                            a_receive_buffer + 
  207.                            p_cur_port_info->rx_tail;
  208.  
  209.                        /* Calculate next tail position
  210.                           in receive buffer */
  211.                        p_cur_port_info->rx_tail += 2;
  212.                        if (p_cur_port_info->rx_tail >=
  213.                            (BUFFER_SIZE * 2) )
  214.                           p_cur_port_info->rx_tail = 0; 
  215.  
  216.                        /* Check for receive buffer 
  217.                           overflow */
  218.                        if (p_cur_port_info->rx_tail ==
  219.                            p_cur_port_info->rx_head)
  220.                            {   /* Receive buffer has 
  221.